package main

import (
	"fmt"
	"net"
	"strings"
)

type Client struct {
	C    chan string //发送数据管道
	Name string
	Addr string
}

var onlineMap map[string]Client
var massage = make(chan string)

func Manager() {
	//给map分配空间
	onlineMap = make(map[string]Client)
	for {
		msg := <-massage //没有消息前会阻塞
		//遍历map给每个map成员发送消息
		for _, client := range onlineMap {
			client.C <- msg
		}

	}
}

func HandlerConnect(conn net.Conn) {
	//获取连接地址
	cliaddr := conn.RemoteAddr().String()
	defer conn.Close()
	//创建客户结构体
	client := Client{
		C:    make(chan string),
		Name: "noname",
		Addr: cliaddr,
	}
	//结构体添加到map内,地址作为key绑定用户
	onlineMap[cliaddr] = client
	//新开携程专门给当前客户端发送信息
	go WriteMassgeToClient(client, conn)
	//广播某人在线
	massage <- MakeMsg(client, "login!")
	//对方是否主动退出
	isQuit := make(chan bool)
	//新建携程处理用户请求
	go SendManager(conn, client, isQuit)
	for {
		//通过select检测isQuit
		select {
		case <-isQuit:
			delete(onlineMap, cliaddr)             //将当前用户从map移除
			massage <- MakeMsg(client, "loginout") //广播谁下线了
			return
		}
	}

}

func SendManager(conn net.Conn, client Client, quit chan bool) {
	buf := make([]byte, 2048)
	for {
		n, err5 := conn.Read(buf)
		if n == 0 {
			quit <- true
			if err5 != nil {
				fmt.Println("读取客户端信息错误：", err5)
			}
			fmt.Println("客户端断开：", err5)
			//用户断开
			return
		}

		msg := string(buf[:n-1])
		fmt.Println(len(msg))
		if len(msg) == 8 && msg == "showuser" {
			//遍历map，给当前用户发送
			conn.Write([]byte("# # user list # #"))
			for _, user := range onlineMap {
				msg := "user: " + user.Name + "   " + "addr:" + "[" + user.Addr + "]" + "\n"
				conn.Write([]byte(string(msg)))
			}
		} else if len(msg) >= 8 && msg[:6] == "rename" {
			//rename|mike
			name := strings.Split(msg, "|")[1]
			client.Name = name
			onlineMap[client.Addr] = client
			conn.Write([]byte("更改Successful!"))
		} else {
			//转发该消息
			massage <- MakeMsg(client, msg)
		}

	}

}

//发送的消息
func MakeMsg(client Client, msg string) (buf string) {
	buf = "[" + client.Addr + "]" + client.Name + ": " + msg
	return buf
}

//发送消息
func WriteMassgeToClient(client Client, conn net.Conn) {
	for msg := range client.C {
		conn.Write([]byte(msg + "\n"))
	}
}
func main() {
	fmt.Println("服务器开启")
	//监听用户
	listener, err := net.Listen("tcp", "127.0.0.1:8000")
	if err != nil {
		fmt.Println("监听错误：", err)
		return
	}
	//最后关闭客户端
	defer listener.Close()
	//新发协程转发消息
	go Manager()

	//主协程循环等待用户连接
	for {
		conn, err1 := listener.Accept()
		if err1 != nil {
			fmt.Println("连接错误：", err1)
			continue
		}
		go HandlerConnect(conn)

	}

}
